package cn.suimg.neo4j.service.impl;

import cn.hutool.core.io.file.FileNameUtil;
import cn.suimg.neo4j.bean.*;
import cn.suimg.neo4j.dto.DownloadFile;
import cn.suimg.neo4j.dto.MusicDownloadInfo;
import cn.suimg.neo4j.dto.SongListShare;
import cn.suimg.neo4j.graph.AlbumGraph;
import cn.suimg.neo4j.mapper.*;
import cn.suimg.neo4j.service.MusicNeoService;
import cn.suimg.neo4j.service.MusicService;
import cn.suimg.neo4j.service.other.KugouService;
import cn.suimg.neo4j.service.other.NetCutService;
import cn.suimg.neo4j.util.EncryptUtil;
import cn.suimg.neo4j.util.HttpClientUtil;
import cn.suimg.neo4j.util.JSONUtil;
import cn.suimg.neo4j.util.ZipBuildUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static cn.suimg.neo4j.config.Constant.TEMP_DIR;

@Slf4j
@Service
@AllArgsConstructor
public class MusicServiceImpl implements MusicService {

    private SongMapper songMapper;

    private SingerImageMapper singerImageMapper;

    private SingerMapper singerMapper;

    private AlbumMapper albumMapper;

    private MusicNeoService musicNeoService;

    private KugouService kugouService;

    private NetCutService netCutService;

    @Override
    public List<SingerImage> searchSingerImage(String hash) {
        List<SingerImage> singerImageList = kugouService.searchSingerImage(hash);
        singerImageList.forEach(image -> {
            if(null == singerImageMapper.selectOne(Wrappers.lambdaQuery(SingerImage.class).eq(SingerImage::getHash,image.getHash()))){
                singerImageMapper.insert(image);
            }
        });
        return singerImageList;
    }


    @Override
    public List<SingerImage> searchSingerImage(int singerId) {
      return searchSingerImage(singerId,null);
    }


    @Override
    public List<SingerImage> searchSingerImage(int singerId, Boolean isMobile) {
        return singerImageMapper.selectList(Wrappers.<SingerImage>lambdaQuery().eq(SingerImage::getSingerId,singerId));
    }

    @Override
    @Cacheable("MusicService")
    public Singer getSingerInfo(Integer singerId) {
        Singer singer = kugouService.querySingerInfo(singerId);
        if(singerMapper.selectById(singer.getId()) == null)
            singerMapper.insert(singer);
        musicNeoService.importSinger(singer);
        return singer;
    }

    @Override
    @Cacheable("MusicService")
    public Album getAlbumById(Integer albumId) {
        Album album = kugouService.queryAlbumInfo(albumId);
        if(albumMapper.selectById(album.getId()) == null)
            albumMapper.insert(album);
        musicNeoService.importAlbum(album);
        return album;
    }

    @Override
    public Song getSongById(Integer songId) {
//         kugouService.querySongDetailInfo(songId);
        return null;
    }

    @Override
    @Cacheable("MusicService")
    public List<Album> getSingerAlbumList(Integer singerId) {
        Singer singer = getSingerInfo(singerId);
        if(singer != null){
            List<Album> albumList = kugouService.querySingerAlbumList(singerId);
            albumList.stream().map(Album::getId).forEach(this::getAlbumById);
            try{
                musicNeoService.importPublishRelationship(singer,albumList);
            }catch (IllegalArgumentException e){ log.warn(e.getMessage()); }
            return albumList;
        }
        return null;
    }

    @Override
    @Cacheable("MusicService")
    public List<Song> getAlbumSongList(Integer albumId) {
        Album album = getAlbumById(albumId);
        if(album != null){
            List<Song> songList = kugouService.querySongListInAlbum(albumId);
            songList.forEach(song -> {
                if(songMapper.selectById(song.getId()) == null)
                    songMapper.insert(song);

                musicNeoService.importSong(song);
                kugouService.querySongTagList(song.getHash()).forEach(tag -> {
                    musicNeoService.importTag(tag);
                    musicNeoService.importAttributeRelationship(tag,song);
                });

                //合唱关系的歌手再丢到MQ
//                songDetailInfo.getSingers().stream().map(Singer::getId).forEach(commitSingerId2MQ);


                searchSingerImage(song.getHash());
            });
            //导入专辑包含歌曲关系
            try{
                musicNeoService.importIncludeRelationship(album,songList);
            }catch (IllegalArgumentException e){ log.warn(e.getMessage()); }
            return songList;
        }
        return null;
    }

    @Override
    public void addSingerFullData(Integer singerId) {
        Singer singer = getSingerInfo(singerId);
        List<Album> albumList = getSingerAlbumList(singerId);
        if(albumList != null){
            albumList.forEach(album -> {
                List<Song> songList = getAlbumSongList(album.getId());
                if(songList != null){
                    //导入歌手演唱歌曲关系
                    try{
                        musicNeoService.importSingRelationship(singer,songList);
                    }catch (IllegalArgumentException e){ log.warn(e.getMessage()); }
                }
            });
        }
    }




    @Override
    public void addSongListShareData(String url) {
        SongListShare share = kugouService.queryShareURLData(url);
        //把歌手ID丢到MQ中
        share.getHashList().forEach(hash -> kugouService.querySingerListBySongHash(hash)
                .stream()
                .map(Singer::getId)
                .forEach(System.out::println)
        );
    }

    @Override
    public List<Integer> getUnprocessedSingerIdList() {
        return singerImageMapper.getUnprocessedSingerIdList();
    }


    @Override
    public String downloadSingerImagesZip(Integer singerId) {

        File tempDir = new File(TEMP_DIR +"/" + UUID.randomUUID().toString());
        tempDir.mkdir();

        singerImageMapper.selectList(Wrappers.<SingerImage>lambdaQuery().eq(SingerImage::getSingerId,singerId)).forEach(singerImage -> {
           try( InputStream inputStream = HttpClientUtil.getInputStream(singerImage.getDownloadUrl());
                OutputStream outputStream = new FileOutputStream(new File(tempDir, singerImage.getHash() +"."+ FileNameUtil.getSuffix(singerImage.getDownloadUrl())));)
           {
               StreamUtils.copy(inputStream,outputStream);
           }catch (IOException e){
               log.error("download file error",e);
           }
        });
        try{
            File zipFile = ZipBuildUtil.compressFolder(tempDir);
            NetCutService.Note note = netCutService.create("hello hello");
            netCutService.uploadFile(note,zipFile);
            log.info("link:{}", JSONUtil.toString(netCutService.renderLink(note)));
            tempDir.delete();
            return netCutService.renderLink(note).getReadOnlyLink();
        }catch (IOException e){
            log.error("make zip file error",e);
        }
        return "";
    }


    @Override
    public List<DownloadFile> getSingerFullData(Integer singerId) {
        List<DownloadFile> downloadFileList = new ArrayList<>();

        Singer singer = singerMapper.selectById(singerId);
        if(singer == null)
            return new ArrayList<>();

        singerImageMapper.selectList(Wrappers.<SingerImage>lambdaQuery().eq(SingerImage::getSingerId,singer.getId())).forEach(singerImage ->
            downloadFileList.add(new DownloadFile(){{
                setSourceUrl(singerImage.getDownloadUrl());
                setDirName(singer.getName() + "/" + "写真集");
                setFileName(singerImage.getHash() +"."+ FileNameUtil.getSuffix(singerImage.getDownloadUrl()));
            }})
        );

        musicNeoService.getSingerAllAlbum(singer.getId()).forEach(albumGraph -> {
           downloadFileList.add(new DownloadFile(){{
               setSourceUrl(albumGraph.getAvatarUrl());
               setDirName(singer.getName() + "/" + albumGraph.getName());
               setFileName("专辑封面."+ FileNameUtil.getSuffix(albumGraph.getAvatarUrl()));
           }});
           musicNeoService.getAlbumAllSong(albumGraph.getAlbumId()).forEach(songGraph -> {

               if(StringUtils.isNotBlank(songGraph.getSqHash())){
                   MusicDownloadInfo sqDownloadInfo = kugouService.queryMusicDownloadUrl(songGraph.getSqHash());
                   if(!sqDownloadInfo.getIgnored())
                       downloadFileList.add(new DownloadFile(){{
                           setSourceUrl(sqDownloadInfo.getUrl());
                           setDirName(singer.getName() + "/" + albumGraph.getName());
                           setFileName(songGraph.getName() + "." + sqDownloadInfo.getExtName());
                       }});
               }else if(StringUtils.isNotBlank(songGraph.getHqHash())){
                   MusicDownloadInfo hqDownloadInfo = kugouService.queryMusicDownloadUrl(songGraph.getHqHash());
                   if(!hqDownloadInfo.getIgnored())
                       downloadFileList.add(new DownloadFile(){{
                           setSourceUrl(hqDownloadInfo.getUrl());
                           setDirName(singer.getName() + "/" + albumGraph.getName());
                           setFileName(songGraph.getName() + "." + hqDownloadInfo.getExtName());
                       }});
               }else if(StringUtils.isNotBlank(songGraph.getHash())) {
                   MusicDownloadInfo musicDownloadInfo = kugouService.queryMusicDownloadUrl(songGraph.getHash());
                   if(!musicDownloadInfo.getIgnored())
                       downloadFileList.add(new DownloadFile() {{
                           setSourceUrl(musicDownloadInfo.getUrl());
                           setDirName(singer.getName() + "/" + albumGraph.getName());
                           setFileName(songGraph.getName() + "." + musicDownloadInfo.getExtName());
                       }});
               }
               if (StringUtils.isNotBlank(songGraph.getMvHash())){
                   String playUrl = kugouService.queryMvPlayUrl(songGraph.getMvHash());
                   if(playUrl != null)
                       downloadFileList.add(new DownloadFile() {{
                           setSourceUrl(playUrl);
                           setDirName(singer.getName() + "/" + albumGraph.getName());
                           setFileName(songGraph.getName() + ".mp4");
                       }});
               }

           });
       });


       return downloadFileList;
    }
}
